"""
斗地主规则引擎 - 最终版本
实现所有标准牌型识别和比较逻辑
"""

from collections import Counter

class RuleEngine:
    @staticmethod
    def validate_play(cards, last_play=None):
        """
        完整牌型验证入口
        :param cards: 当前出的牌列表（空列表表示不出）
        :param last_play: 上家出的牌 (cards, play_type)
        :return: (是否合法, 牌型信息)
        """
        # 不出牌总是合法
        if not cards:
            return True, ('pass', 0, 0)

        # 识别牌型
        play_type = RuleEngine._identify_pattern(cards)
        if not play_type:
            return False, None

        # 首家出牌直接合法
        if not last_play or last_play[1][0] == 'pass':
            return True, play_type

        # 比较牌型大小
        return RuleEngine._compare_plays(play_type, last_play[1]), play_type

    @staticmethod
    def _identify_pattern(cards):
        """核心牌型识别逻辑"""
        values = sorted([c.value for c in cards])
        counter = Counter(values)
        card_count = len(cards)

        # 火箭（必须优先判断）
        if set(values) == {14, 15} and card_count == 2:
            return ('rocket', 15, 2)

        # 炸弹（四张相同）
        if card_count == 4 and len(counter) == 1:
            return ('bomb', values[0], 4)

        # --- 单牌类型 ---
        if card_count == 1:
            return ('single', values[0], 1)

        # --- 对牌类型 ---
        if card_count == 2 and len(counter) == 1:
            return ('pair', values[0], 2)

        # --- 三张类型 ---
        if card_count == 3 and len(counter) == 1:
            return ('triple', values[0], 3)

        # --- 三带一 ---
        if card_count == 4:
            triple = [v for v, c in counter.items() if c == 3]
            if len(triple) == 1:
                return ('triple+single', triple[0], 4)

        # --- 三带对 ---
        if card_count == 5:
            if sorted(counter.values()) == [2, 3]:
                return ('triple+pair', max(counter), 5)

        # --- 顺子 ---
        if 5 <= card_count <= 12:
            if RuleEngine._is_continuous(values) and len(counter) == card_count:
                return ('sequence', max(values), card_count)

        # --- 连对 ---
        if card_count >= 6 and card_count % 2 == 0:
            pairs = sorted([v for v, c in counter.items() if c == 2])
            if len(pairs) * 2 == card_count and RuleEngine._is_continuous(pairs):
                return ('chain_pair', max(pairs), card_count)

        # --- 飞机（无翅膀）---
        triples = sorted([v for v, c in counter.items() if c == 3])
        if len(triples) >= 2 and RuleEngine._is_continuous(triples):
            # 纯飞机（如333444）
            if len(triples) * 3 == card_count:
                return ('aircraft', max(triples), card_count)
            # 飞机带单翅
            if len(triples) * 4 == card_count and all(c in [1, 3] for c in counter.values()):
                return ('aircraft+single', max(triples), card_count)
            # 飞机带双翅
            if len(triples) * 5 == card_count and Counter(counter.values())[2] == len(triples):
                return ('aircraft+pair', max(triples), card_count)

        # --- 四带二 ---
        if card_count == 6:
            quads = [v for v, c in counter.items() if c == 4]
            if quads:
                return ('quad+dual', quads[0], 6)
        if card_count == 8:
            if sorted(counter.values()) == [2, 2, 4]:
                return ('quad+dual_pair', max(counter), 8)

        return None

    @staticmethod
    def _is_continuous(values):
        """检查是否连续序列"""
        return all(values[i] + 1 == values[i+1] for i in range(len(values)-1))

    @staticmethod
    def _compare_plays(current, last):
        """
        牌型比较逻辑
        :param current: 当前牌型 (type, value, size)
        :param last: 上家牌型
        :return: 当前牌是否大过上家
        """
        # 火箭必胜
        if current[0] == 'rocket':
            return True
        if last[0] == 'rocket':
            return False

        # 炸弹压制非炸弹
        if current[0] == 'bomb' and last[0] != 'bomb':
            return True
        if last[0] == 'bomb' and current[0] != 'bomb':
            return False

        # 同类牌型比较
        if current[0] == last[0] and current[2] == last[2]:
            return current[1] > last[1]

        # 特殊规则：炸弹比较
        if current[0] == 'bomb' and last[0] == 'bomb':
            return current[1] > last[1]

        return False

    @staticmethod
    def get_hierarchy():
        """获取牌型压制关系（用于调试）"""
        return {
            'rocket': 10,
            'bomb': 9,
            'quad+dual_pair': 8,
            'aircraft+pair': 7,
            'aircraft+single': 6,
            'aircraft': 5,
            'chain_pair': 4,
            'sequence': 3,
            'triple+pair': 2,
            'triple+single': 1,
            'pair': 0,
            'single': -1
        }